<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, nextTick, useSlots } from "vue";
import { ArrowRightBold } from "@px-ui/icons-vue";
import echartsCom from "../echartsCom/index.vue";
import modelTitle from "@/views/common/components/modelTitle/index.vue";
import { emitter } from "@/utils/mitt";
import type { LabelLayoutFunctionType, EchartsInstanceFunctionType } from "../types";
import { useInitLoading } from "@/hooks/useCommon";
import { loadingTimeout } from "@/utils/http/constant";

interface Props {
  /**  获取当前echarts实例对象，参数为实例对象和回调函数 */
  getEchartsInstance?: EchartsInstanceFunctionType | null;
  /**  获取 optiins 配置函数 */
  labelLayoutFn?: LabelLayoutFunctionType | null;
  /**  同 echarts option */
  options?: CommonEcharts.CommonEchartsOption | null;
  /**  有 title 时传入 */
  title?: string;
  /**  有按钮时传入，传入后会有 btn-click 事件 */
  button?: string;
  /**  右侧箭头按钮 */
  arrow?: boolean;
  /**  右侧下载按钮 */
  showDownload?: boolean;
  /**  title 栏右侧文字 */
  rightText?: string | number;
  /**  模块最低宽度，默认 330px */
  width?: number;
  /**  模块最低高度，默认 200px */
  height?: number;
  /**  是否需要背景阴影，默认为true */
  boxShadow?: boolean;
  /**  是否需要圆角，默认为true */
  borderRidus?: boolean;
  /**  是否dark模式 */
  dark?: boolean;
  /** 不加边框 */
  noBorder?: boolean;
  /** 不加左右padding */
  noPadding?: boolean;
  /** 标题背景渐变宽度 */
  titleBgWidth?: number | string;
}

const props = withDefaults(defineProps<Props>(), {
  width: 200,
  height: 160,
  arrow: false,
  showDownload: false,
  boxShadow: false,
  borderRidus: true,
  dark: false,
  noBorder: false,
  padding: 16
});

interface Emits {
  /**  title 右侧按钮点击后触发 */
  (event: "btn-click"): void;
}

const emits = defineEmits<Emits>();

const slot = useSlots();
const echartsKey = ref<string>(`echartsKey_${Math.random().toString(36).slice(2, 10)}`);
const echartsComRef = ref<InstanceType<typeof echartsCom> | null>(null);
const echartsChartComClass = ref<string>(`echartsChart_${Math.random().toString(36).slice(2, 10)}`);
const loadingInstance = ref<any>(null);

const title_height = computed(() => (props.title ? "38px" : "0px"));
const min_width = computed(() => `${props.width}px`);
const min_height = computed(() => `${props.height}px`);
const chartClass = computed(() => {
  const { boxShadow, borderRidus, dark, noBorder, noPadding } = props;
  let classCom = {
    boxShadow,
    borderRidus
  };
  if (!noBorder) {
    classCom = {
      ...classCom,
      "echarts-chart-dark": dark
    };
  } else {
    classCom = {
      ...classCom,
      "echarts-chart-dark-noborder": dark
    };
  }
  if (noPadding) {
    classCom = {
      ...classCom,
      noPadding
    };
  }
  return classCom;
});

const clickHandler = () => emits("btn-click");

const updateEchartsKey = () => {
  emitter.on("viceMenuChange", () => {
    echartsKey.value = `echartsKey_${Math.random().toString(36).slice(2, 10)}`;
  });
};

const getEcharts = async () => {
  await nextTick();
  return echartsComRef.value.getEcharts();
};

const initLoading = () => {
  const target = `.${echartsChartComClass.value}`;
  loadingInstance.value = useInitLoading(target, props.dark);
  setTimeout(() => {
    loadingInstance.value.close();
  }, loadingTimeout);
  return loadingInstance.value;
};

const updateEchartsOption = (flag: boolean = true) => {
  echartsComRef.value.updateOption(flag);
};

const forceUpdateEcharts = () => {
  echartsKey.value = `echartsKey_${Math.random().toString(36).slice(2, 10)}`;
};

const clearEchartsData = async () => {
  const { clear } = await echartsComRef.value.getEcharts();
  clear && clear();
};

onMounted(async () => {
  updateEchartsKey();
});

onUnmounted(() => {
  emitter.off("viceMenuChange");
});

defineExpose({
  loadingInstance,
  getEcharts,
  initLoading,
  updateEchartsOption,
  forceUpdateEcharts,
  clearEchartsData
});
</script>

<template>
  <div class="echarts-chart" :class="chartClass">
    <modelTitle v-if="title" :title="title" :dark="dark" :titleBgWidth="titleBgWidth">
      <div class="model-title-slot">
        <div v-if="slot.default" class="echarts-chart-title-slot"><slot /></div>
        <span v-else-if="rightText || rightText == '0'" class="right-text">{{ rightText }}</span>
        <px-button v-else-if="button" type="primary" size="small" plain @click="clickHandler">{{ button }}</px-button>
        <px-button v-else-if="arrow" class="px-button-arrow" :icon="ArrowRightBold" type="primary" text plain @click="clickHandler" />
        <px-icon v-else-if="showDownload" color="#3B82F6" @click="clickHandler"><Download /></px-icon>
      </div>
    </modelTitle>
    <div :class="['echarts-chart-com', echartsChartComClass]">
      <echartsCom
        ref="echartsComRef"
        :key="echartsKey"
        :dark="dark"
        :getEchartsInstance="getEchartsInstance"
        :labelLayoutFn="labelLayoutFn"
        :options="options"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.echarts-chart {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
  width: 100%;
  min-width: v-bind(min_width);
  height: 100%;
  min-height: v-bind(min_height);
  padding: 16px;
  background-color: #fff;

  .model-title-slot {
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;

    .right-text {
      font-weight: 600;
      line-height: 1;
      color: var(--px-color-primary);
    }

    .echarts-chart-title-slot {
      width: 100%;
      height: 100%;
    }

    .px-button-arrow {
      padding-right: 0;
      // color: var(--pa-color-primary);
    }

    .px-icon {
      cursor: pointer;
    }
  }

  .echarts-chart-com {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: calc(100% - v-bind(title_height));
  }
}

.boxShadow {
  box-shadow: 0 0 10px rgb(0 37 86 / 12%);
}

.borderRidus {
  border-radius: 4px;
}

.noPadding {
  padding: 0;
}

.echarts-chart-dark {
  background-color: #001e3bff;
  border: 1px solid #83b2ffff;
  box-shadow: inset 0 0 10px 0 #83b2ffff;
}

.echarts-chart-dark-noborder {
  background-color: #001e3bff;
}
</style>
